#include <iostream>
#include <fstream>
#include <ctime>

#ifdef THREAD
	#include <pthread.h>
#endif

#include "Analysis.h"

using namespace std;

#ifdef THREAD
void* MakeThread(void* data)
{
	CAnalysis* function=*((CAnalysis**)data);
	CMap* map=*((CMap**)data+1);
	int indexType=*((int*)data+2);
	CMatrix* matrix=*((CMatrix**)data+3);
	int matType=*((int*)data+4);
	int outMapType=*((int*)data+5);

	switch(outMapType)
	{
		case FREQ :
			break;
		default :
			function->CalcDensity(map, indexType, matrix,  matType, outMapType);
	}

	return NULL;
}
#endif

int main(int argc, char* argv[])
{
//----------------------------------------------------------------//
//   Global variables                                             //
//----------------------------------------------------------------//

	char g_verIndex[256]="development 1.0.18";
	int g_mapHeight=0;
	int g_mapWidth=0;

	cout<<endl;
	cout<<"Multi-resolution Analysis for the Area Density Map"<<endl;
	cout<<"coded by Sungshil Kim with the standard GNU C++"<<endl;
	cout<<"Version: "<<g_verIndex<<endl<<endl;

//----------------------------------------------------------------//
//   Main processes for analysis                                  //
//----------------------------------------------------------------//

	#ifdef ADV_OPTIONS

	CMap* Map=new CMap();
	g_mapHeight=Map->GetHeight();
	g_mapWidth=Map->GetWidth();

	CMatrix* Matrix=new CMatrix();
	Matrix->SetMapSize(g_mapHeight, g_mapWidth);

	#endif

	#ifndef ADV_OPTIONS

	CMap* Map=new CMap(&g_mapHeight, &g_mapWidth);

	CMatrix* Matrix=new CMatrix(g_mapHeight, g_mapWidth);

	#endif

	CAnalysis* Function=new CAnalysis();

	#ifdef ADV_OPTIONS

	int g_start, g_end;

	g_start=time(NULL);

	#endif

	cout<<"Start analysis..."<<endl;

	#ifndef THREAD

	Function->CalcDensity(Map, INDEX, Matrix, ISOTROPIC, DENSITY);

	Function->CalcDensity(Map, MAXIMUM, Matrix, ISOTROPIC, MAX);

	Function->CalcDensity(Map, INDEX, Matrix, HORIZONTAL, HOR);

	Function->CalcDensity(Map, INDEX, Matrix, VERTICAL, VER);

	#endif

	#ifdef THREAD

	int numThread=4;
	int numParameter=6;
	int ii, jj;

	int thread_id[numThread];
	pthread_t p_thread[numThread];
	int status[numThread];

	void* dataList[numThread][numParameter];

	for(ii=0;ii<numThread;ii++)
	{
		thread_id[ii]=0;
		p_thread[ii]=0;
		status[ii]=0;
		for(jj=0;jj<numParameter;jj++)
			dataList[ii][jj]=NULL;
	}

	//Thread ID 0
	dataList[0][0]=Function;
	dataList[0][1]=Map;
	dataList[0][2]=(void*)(INDEX);
	dataList[0][3]=Matrix;
	dataList[0][4]=(void*)(ISOTROPIC);
//	dataList[0][4]=(void*)(SQUARE);
	dataList[0][5]=(void*)(DENSITY);

	//Thread ID 1
	dataList[1][0]=Function;
	dataList[1][1]=Map;
	dataList[1][2]=(void*)(MAXIMUM);
	dataList[1][3]=Matrix;
	dataList[1][4]=(void*)(ISOTROPIC);
	dataList[1][5]=(void*)(MAX);

	//Thread ID 2
	dataList[2][0]=Function;
	dataList[2][1]=Map;
	dataList[2][2]=(void*)(INDEX);
	dataList[2][3]=Matrix;
	dataList[2][4]=(void*)(HORIZONTAL);
	dataList[2][5]=(void*)(HOR);

	//Thread ID 3
	dataList[3][0]=Function;
	dataList[3][1]=Map;
	dataList[3][2]=(void*)(INDEX);
	dataList[3][3]=Matrix;
	dataList[3][4]=(void*)(VERTICAL);
	dataList[3][5]=(void*)(VER);

	for(ii=0;ii<numThread;ii++)
		thread_id[ii]=pthread_create(&p_thread[ii], NULL, MakeThread, dataList[ii]);

	for(ii=0;ii<numThread;ii++)
		pthread_join(p_thread[ii], (void**)&status[ii]);

	#endif

/*
	DENSITYMAP ttt=Map->MakeDensityMap();
	Map->DeleteDensityMap(ttt);
*/

	cout<<"Writting data files..."<<endl;

	Function->PrintStatistics(Map, Matrix);
	Map->Print2DList(DENSITY);

	#ifdef ADV_OPTIONS

	Matrix->Print2DList(ISOTROPIC);
//	Matrix->Print2DList(SQUARE);
//	Map->Print2DList(MAX);
	Map->Print2DList(HOR);
	Map->Print2DList(VER);
	Map->Print2DList(SIZE);
	Map->Print2DList(CLUSTER);
	Map->Print2DList(FREQ);
	Map->PrintASCIIMap(DENSITY);
	Map->PrintGrASCIIMap(DENSITY);
	Map->PrintGrainList();
	Map->PrintList(DENSITY);

	#endif


	cout<<"Completed."<<endl<<endl;

	delete Matrix;
	delete Map;
	delete Function;

	#ifdef ADV_OPTIONS

	g_end=time(NULL);
	cout<<"run time: "<<(g_end-g_start)/60<<"min "
		<<(g_end-g_start)%60<<"sec"<<endl;

	#endif

	return (0);
}

